var boi_ui = {
    debugWindow: null,
    actions: {
        read: "READ",
        update: "UPDATE",
        del: "DELETE",
        create: "CREATE"
    },
    render: {
        loading: function(href)
        {
            var src = "img/ajax-loader.gif";
            if(href.indexOf('/comp/') > -1)
                src = "../" + src;
            return '<img class="bi_loading" style="position: absolute;" src="' + src + '" alt="loading.."/>';
        }
    },
    check:{
        validateRole: function(role, fn){

            var req = boi_ui.request.prepare('ZCL_MYBW_GEN_SERVICES', boi_ui.actions.read,
                [boi_ui.data.createRecord({"TYPE": ["VALIDATE_ROLE"], "ROLE": [role]})]);
            boi_ui.request.perform(req,'xml','POST',function(data){
                if($(data).find('STATUS').text() == 'F')
                    fn(false);
                else
                    fn(true);
            });
        }
    },
    read: {
        getApp: function(app_id, fn){
            var record = boi_ui.data.createRecord({"APP_ID": [app_id], "USER_TYPE": ["ADMIN"]});
            var req = boi_ui.request.prepare("ZCL_MYBW_APP_CATALOG", boi_ui.actions.read, [record]);

            boi_ui.request.perform(req,"text","POST",fn);
        },
        getNode: function(app_id, tech_name, fn, debugIn){
            var record = boi_ui.data.createRecord({"APP_ID": [app_id], "TECH_NAME": [tech_name]});
            var req = boi_ui.request.prepare("ZCL_MYBW_REP_CATALOG", boi_ui.actions.read, [record]);
            if(debugIn) debugIn.val(req);
            boi_ui.request.perform(req,"text","POST",fn);

        },
        getTemplate: function(app_id, template_id, fn){
            var record = boi_ui.data.createRecord({"APP_ID":[app_id], "TEMPLATE_ID": [template_id]});
            var req = boi_ui.request.prepare("ZCL_MYBW_VAR_TEMPLATE", boi_ui.actions.read, [record] );
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getView: function(app_id, view_id, fn){
            var record = boi_ui.data.createRecord({"APP_ID":[app_id], "VIEW_ID": [view_id]});
            var req = boi_ui.request.prepare("ZCL_MYBW_VAR_VIEW", boi_ui.actions.read, [record] );
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getComponent: function(app_id, comp_id, fn){
            var record = boi_ui.data.createRecord({"APP_ID":[app_id], "COMP_ID": [comp_id]});
            var req = boi_ui.request.prepare("ZCL_MYBW_COMPONENT", boi_ui.actions.read, [record] );
            boi_ui.request.perform(req,"text","POST",fn);
        }
    },
    list: {
        getApps: function(fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_APP_CATALOG", boi_ui.actions.read,
                [
                    boi_ui.data.createRecord({
                        "OUTPUT_FORMAT": ["JSON"],
                        "USER_TYPE": ["ADMIN"]
                    })
                ]);
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getUserApps: function(fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_GEN_SERVICES", boi_ui.actions.read,
                [
                    boi_ui.data.createRecord({
                        "TYPE": ["GET_APPS"]
                    })
                ]);
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getCatalog: function(app_id, fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_REP_CATALOG", boi_ui.actions.read,
                [
                    boi_ui.data.createRecord({"APP_ID": [app_id],
                        "OUTPUT_FORMAT": ["JSON"],
                        "USER_TYPE": ["ADMIN"]
                    })
                ]);
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getTemplates: function(app_id, type, fn){
            if(app_id == undefined) app_id = "ALL";
            var req = boi_ui.request.prepare("ZCL_MYBW_VAR_TEMPLATE", boi_ui.actions.read,
                [boi_ui.data.createRecord({"APP_ID": [app_id], "TYPE": [type]})]);
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getVariableViews: function(app_id, fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_VAR_VIEW", boi_ui.actions.read, [boi_ui.data.createRecord( {"APP_ID": [app_id], "VIEW_ID": [""]})]);
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getComponents: function(app_id, fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_COMPONENT", boi_ui.actions.read, [boi_ui.data.createRecord( {"APP_ID": [app_id]})]);
            boi_ui.request.perform(req,"text","POST",fn);
        },
        getProperties: function(app_id, comp_id, fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_COMP_PROP", boi_ui.actions.read, [boi_ui.data.createRecord( {"APP_ID": [app_id], "COMP_ID": [comp_id]})]);
            boi_ui.request.perform(req,"text","POST",fn);
        }
    },
    lookup:{
        getConfig: function(){},
        getNodeTypes: function(fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_PARAMETER", boi_ui.actions.read,[boi_ui.data.createRecord({"CONTEXT": ['NODE_TYPE']})]);
            boi_ui.request.perform(req,'text','POST',fn);
        },
        getOpenStyles: function(fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_PARAMETER", boi_ui.actions.read,[boi_ui.data.createRecord({"CONTEXT": ['OPEN_STYLE']})]);
            boi_ui.request.perform(req,'text','POST',fn);
        },
        getF4Modes: function(fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_PARAMETER", boi_ui.actions.read,[boi_ui.data.createRecord({"CONTEXT": ['F4_MODE']})]);
            boi_ui.request.perform(req,'text','POST',fn);
        },
        getSelectionTypes: function(fn){
            var req = boi_ui.request.prepare("ZCL_MYBW_PARAMETER", boi_ui.actions.read,[boi_ui.data.createRecord({"CONTEXT": ['SEL_TYPE']})]);
            boi_ui.request.perform(req,'text','POST',fn);
        }
    },
    app_id: 'ALL',
    request:{
        prepare: function(class_name, method_name, records){
            var request = $("<DATA></DATA>");

            for(var i in records)
            {
                records[i].app_id = boi_ui.app_id;
                records[i].class_name = class_name;
                records[i].method_name = method_name;
                request.append(records[i].toString());
            }

            return boi_ui.util.htmlToXml(request);
        },
        perform: function(request, datatype, method, successFunction){
            request = '<?xml version="1.0"?>' + request;
            var url = window.location.href;
            var ajaxurl = url.substr(0, url.indexOf('/bc/bsp/sap/')) + "/bc/bsp/sap/zbi_integration/bi_app_factory.xml";

            var reqStr = '\n\n************* BEGIN REQUEST ******************\n\n'
                + request.replace(/></g,'>\n<')
                + '\n\n************* END REQUEST ******************\n\n';
            if(boi_ui.debugWindow)
                boi_ui.debugWindow.val(boi_ui.debugWindow.val() + reqStr);

            $.ajax({
                url: ajaxurl,
                data: request,
                type: method,
                contentType: 'multipart/form-data',
                dataType: datatype,
                success: function(data)
                {
                    var output = "";
                    if(datatype == 'xml')
                        output = $(data).html();
                    else
                        output = data.replace(/></g,'>\n<');

                    var respStr = '\n\n************* BEGIN RESPONSE ******************\n\n'
                        + output
                        + '\n\n************* END RESPONSE ******************\n\n';
                    if(boi_ui.debugWindow)
                        boi_ui.debugWindow.val(boi_ui.debugWindow.val() + respStr);

                    if(datatype == 'xml' && $(data).find('STATUS').get(0))
                    {
                        if($(data).find('STATUS').text() == 'F')
                            alert($(data).find('MESSAGE').text());
                        else if(successFunction)
                        {
                            try{successFunction(data);}
                            catch(e) {}
                        }
                    }
                    else
                    {
                        if(successFunction)
                        {
                            try{//textual, remove xml tag <?xml version="1.0"?>
                                data = data.replace('<?xml version="1.0"?>','');
                                successFunction(data);
                            }
                            catch(e) {}
                        }
                    }
                },
                error: function (xhr, ajaxOptions, thrownError)
                {
                    var respStr = '\n\n************* BEGIN RESPONSE ******************\n\n'
                        + '\n\n--- Status ---\n\n'
                        + xhr.status + ', ERROR: '
                        + thrownError + ', RESPONSE:\n\n'
                        + xhr.responseText
                        + '\n\n************* END RESPONSE ******************\n\n';
                    if(boi_ui.debugWindow)
                        boi_ui.debugWindow.val(boi_ui.debugWindow.val() + respStr);

                    alert('\n\n--- Request ---\n\n' + request
                        + '\n\n--- Status ---\n\n'
                        + xhr.status + ': '
                        + thrownError );
                    //console.log(xhr.status + '\n\n' + request + '\n\n'+  xhr.responseText + '\n\n'+ thrownError);
                }
            });
        }
    },
    data: {
        createRecord: function(params){ //create from hashset
            var record = new boi_ui.Record();
            for(var i in params)
            {
                var param = new boi_ui.Parameter();
                param.name = i;
                for(var v in params[i])
                    param.values.push(params[i][v]);

                record.parameters.push(param);
            }
            return record;
        }
    },
    util:{
        htmlToXml: function(request){
            //convert html to XML (handling capitalization)
            var pattern = /<([\/]*)([a-zA-Z_0-9]+)([^>]*)>/g;

            request = request[0].outerHTML.replace(pattern, function(full, before, tag, after) {
                return "<" + before + tag.toUpperCase() + after + ">"
            });

            return request;
        },
        htmlEncode: function (str) {
            return String(str)
                .replace(/&/g, '&amp;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#39;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;');
        },
        getParameterByName: function(querystring, name){
            name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
            var regexS = "[\\?&]" + name + "=([^&#]*)";
            var regex = new RegExp(regexS);
            var results = regex.exec(querystring);
            if(results == null)
                return "";
            else
                return decodeURIComponent(results[1].replace(/\+/g, " "));
        },
        isXML: function(text) {
            var isXml = true;
            try{
                isXml = $.parseXML(text);
            }
            catch(e){
                isXml = false;
            }
            return isXml;
        }
    },
    Record: function()
    {
        this.app_id = "ALL";
        this.class_name = "";
        this.method_name = "";
        this.parameters = [];

        this.toString = function(){
            var output = "<RECORD><CLASS_NAME>" + this.class_name + "</CLASS_NAME><METH_NAME>"
                + this.method_name + "</METH_NAME><APP_ID>"
                + this.app_id + "</APP_ID>";
            for(var i in this.parameters)
                output += this.parameters[i].toString();
            output+= '</RECORD>';
            return boi_ui.util.htmlToXml($(output));
        };
    },
    Parameter: function()
    {
        this.name = "";
        this.values = [];
        this.toString = function(){
            var output = "<PARAMETER><NAME>" + this.name + "</NAME>";
            //var values = $('');
            for (var i in this.values)
                output+='<VALUES><VALUE>' + boi_ui.util.htmlEncode(this.values[i]) + '</VALUE></VALUES>';

            if(this.values.length == 0)
                output+='<VALUES><VALUE></VALUE></VALUES>';
            output+='</PARAMETER>';
            return boi_ui.util.htmlToXml($(output));
        };
    }
};
